package com.gitee.yusugar.pay.alipay.core;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayObject;
import com.alipay.api.AlipayResponse;
import com.alipay.api.domain.AlipayTradeCloseModel;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.gitee.yusugar.pay.alipay.config.AlipayConfig;
import com.gitee.yusugar.common.pojo.DataRes;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AlipayService {
    private final Logger LOG = LoggerFactory.getLogger( AlipayService.class );

    @Setter
    protected AlipayConfig alipayConfig;

    /**
     * 交易下单（创建订单）
     *
     * @param model     数据
     * @param notifyUrl 异步回调
     * @param returnUrl 同步回调
     * @return 结果
     */
    public abstract DataRes<String> tradePay( AlipayObject model, String notifyUrl, String returnUrl );

    /**
     * 交易下单（创建订单）
     *
     * @param model 数据
     * @return 结果
     */
    public DataRes<String> tradePay( AlipayObject model ) {
        return tradePay( model, null, null );
    }

    /**
     * 退款
     *
     * @param model     数据
     * @param notifyUrl 异步回调
     * @param returnUrl 同步回调
     * @return 结果
     */
    public DataRes<String> refund( AlipayTradeRefundModel model, String notifyUrl, String returnUrl ) {
        AlipayClient alipayClient = alipayConfig.buildAlipayClient();

        AlipayTradeRefundRequest refundRequest = new AlipayTradeRefundRequest();
        refundRequest.setNotifyUrl( StrUtil.isBlank( notifyUrl ) ? alipayConfig.getNotifyUrl() : notifyUrl );
        refundRequest.setReturnUrl( StrUtil.isBlank( returnUrl ) ? alipayConfig.getReturnUrl() : returnUrl );

        refundRequest.setBizModel( model );

        try {
            AlipayTradeRefundResponse response = alipayClient.execute( refundRequest );

            if ( response.isSuccess() )
                return DataRes.data( response.getOutTradeNo() );

            return errorOrderNoRecord( response, response.getOutTradeNo(), "订单退款异常" );
        } catch ( AlipayApiException e ) {
            return errorRecord( e, "订单退款异常" );
        }
    }

    /**
     * 退款
     *
     * @param model 数据
     * @return 结果
     */
    public DataRes<String> refund( AlipayTradeRefundModel model ) {
        return refund( model, null, null );
    }

    /**
     * 查询交易接口
     *
     * @param model 查询参数
     * @return 订单信息
     */
    public DataRes<String> queryPayInfo( AlipayTradeQueryModel model ) {
        AlipayClient alipayClient = alipayConfig.buildAlipayClient();

        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizModel( model );

        try {
            AlipayTradeQueryResponse response = alipayClient.execute( request );
            if ( response.isSuccess() )
                return DataRes.data( response.getBody() );

            return errorOrderNoRecord( response, response.getOutTradeNo(), "查询交易订单异常" );
        } catch ( AlipayApiException e ) {
            return errorRecord( e, "查询交易订单异常" );
        }
    }

    /**
     * 查询退款接口
     *
     * @param model 查询参数
     * @return 订单信息
     */
    public DataRes<String> queryRefundInfo( AlipayTradeFastpayRefundQueryModel model ) {
        AlipayClient alipayClient = alipayConfig.buildAlipayClient();

        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        request.setBizModel( model );

        try {
            AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute( request );
            if ( response.isSuccess() )
                return DataRes.data( response.getBody() );

            return errorOrderNoRecord( response, response.getOutTradeNo(), "查询退款订单异常" );
        } catch ( AlipayApiException e ) {
            return errorRecord( e, "查询退款订单异常" );
        }
    }

    /**
     * 交易关闭接口
     *
     * @param model 参数
     * @return 是否成功
     */
    public DataRes<String> tradeClose( AlipayTradeCloseModel model ) {
        AlipayClient alipayClient = alipayConfig.buildAlipayClient();

        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();

        request.setBizModel( model );

        try {
            AlipayTradeCloseResponse response = alipayClient.execute( request );
            if ( response.isSuccess() )
                return DataRes.success();

            return errorOrderNoRecord( response, response.getOutTradeNo(), "订单关闭异常" );
        } catch ( AlipayApiException e ) {
            return errorRecord( e, "订单关闭异常" );
        }
    }

    /**
     * 对账单
     *
     * @param type 账单类型
     * @param date 账单日期
     * @return 是否成功
     */
    public DataRes<String> downBill( String type, String date ) {
        AlipayClient alipayClient = alipayConfig.buildAlipayClient();

        AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();

        JSONObject params = new JSONObject();
        params.put( "bill_type", type );
        params.put( "bill_date", date );
        request.setBizContent( params.toString() );

        try {
            AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute( request );

            if ( response.isSuccess() )
                return DataRes.data( response.getBillDownloadUrl() );

            return errorOrderNoRecord( response, "未知编号", "对账单下载异常" );
        } catch ( AlipayApiException e ) {
            return errorRecord( e, "对账单下载异常" );
        }
    }

    protected DataRes<String> errorOrderNoRecord( AlipayResponse response, String orderNo, String errorStr ) {
        LOG.error( "订单号：【{}】,【{}】,状态码【{}】【{}】,错误信息【{}】【{}】", orderNo, errorStr,
                response.getCode(), response.getSubCode(), response.getMsg(), response.getSubMsg() );
        return DataRes.fail( response.getCode(), response.getSubMsg() );
    }

    protected DataRes<String> errorRecord( AlipayApiException e, String errorStr ) {
        LOG.error( "【{}】,状态码【{}】,错误信息【{}】", errorStr, e.getErrCode(), e.getErrMsg() );
        return DataRes.fail( e.getErrCode(), e.getErrMsg() );
    }

}
